﻿using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.CodeDom.Compiler;
using EnvDTE;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.ComponentModel.Design.Serialization;

using System.IO;
using System.Diagnostics;
using System.Xml;
using System.Globalization;

namespace Adaptive.Foundation.CodeDom.Native
{
    /// <summary>
    /// 
    /// </summary>
    internal class CodeDomXmlProcessor
    {
        // Fields
        /// <summary>
        /// 
        /// </summary>
        private static Hashtable binopTable = null;
        /// <summary>
        /// 
        /// </summary>
        private static TraceSwitch CodeDOMXmlParseSwitch = new TraceSwitch("CodeDOMXmlProcessor", "CodeDOMXmlProcessor: Debug XML processing");
        private Hashtable createHandlers = new Hashtable();
        private string curAttrName;
        private XmlElementData currentElement;
        private Stack elementStack = new Stack();
        private string fileName;
        private Stack garbagePile = new Stack();
        private bool handlersInitialized;
        private Stack itemStack = new Stack();
        internal const string KeyXmlParsedStatement = "_XmlCodeDomParseStmt";
        private CodeLinePragma lastLinePragma;
        private string methodName;
        private static string[] NameTableStrings = new string[] { 
        "Array", "Expression", "Type", "scope", "variablekind", "Null", "Number", "Boolean", "Char", "String", "true", "ArrayType", "Local", "Argument", "static", "shadows", 
        "overrides", "sealed", "virtual", "abstract", "ExpressionStatement", "name", "Name", "line", "NameRef", "NewArray", "Assignment", "BinaryOperation", "Cast", "NewDelegate", "MethodCall", "NewClass", 
        "Literal", "PropertyAccess", "ThisReference", "Parenthesis", "ArrayElementAccess", "Block", "plus", "concatenate", "equals", "removedelegate", "adddelegate"
     };
        private ArrayList topLevelItems = new ArrayList();

        // Methods
        public void CData(string text)
        {
        }

        public void CharEntity(string name, char value)
        {
        }

        public void Comment(string body)
        {
        }

        private object CreateArrayCreateExpression(XmlElementData xmlElement)
        {
            string elementType = this.GetElementType(xmlElement);
            if (elementType.EndsWith("[]"))
            {
                elementType = elementType.Substring(0, elementType.Length - 2);
            }
            XmlElementData[] dataArray = xmlElement.Children["Expression"];
            CodeExpression[] array = null;
            int size = -1;
            if (dataArray == null)
            {
                array = new CodeExpression[0];
            }
            else
            {
                ArrayList list = new ArrayList();
                for (int i = 0; i < dataArray.Length; i++)
                {
                    CodeExpression expression = (CodeExpression)this.CreateExpressionElement(dataArray[i]);
                    if (expression is CodeArrayExpression)
                    {
                        list.AddRange(((CodeArrayExpression)expression).CreateValueArray());
                    }
                    else
                    {
                        list.Add(expression);
                    }
                }
                if (list.Count > 0)
                {
                    array = new CodeExpression[list.Count];
                    list.CopyTo(array, 0);
                }
                else
                {
                    XmlElementData data = xmlElement.Children.FirstChild("Bound");
                    if (data != null)
                    {
                        CodePrimitiveExpression elementExpression = this.GetElementExpression(data) as CodePrimitiveExpression;
                        if ((elementExpression != null) && (elementExpression.Value is int))
                        {
                            size = (int)elementExpression.Value;
                        }
                    }
                }
            }
            if (size == -1)
            {
                return new CodeArrayCreateExpression(elementType, array);
            }
            return new CodeArrayCreateExpression(elementType, size);
        }

        private object CreateArrayExpression(XmlElementData xmlElement)
        {
            XmlElementData[] dataArray = xmlElement.Children["Array"];
            CodeArrayExpression expression = new CodeArrayExpression();
            if (dataArray.Length == 0)
            {
                dataArray = xmlElement.Children["Expression"];
            }
            if (dataArray != null)
            {
                foreach (XmlElementData data in dataArray)
                {
                    CodeExpression expression2 = this.CreateExpressionElement(data) as CodeExpression;
                    if (expression2 != null)
                    {
                        expression.Values.Add(expression2);
                    }
                }
            }
            return expression;
        }

        private object CreateArrayIndexerExpression(XmlElementData xmlElement)
        {
            XmlElementData[] dataArray = xmlElement.Children["Expression"];
            CodeExpression targetObject = (CodeExpression)this.CreateExpressionElement(dataArray[0]);
            CodeExpression[] indices = new CodeExpression[dataArray.Length - 1];
            for (int i = 1; i < dataArray.Length; i++)
            {
                indices[i - 1] = (CodeExpression)this.CreateExpressionElement(dataArray[i]);
            }
            return new CodeArrayIndexerExpression(targetObject, indices);
        }

        private object CreateArrayTypeReferenceExpression(XmlElementData xmlElement)
        {
            int rank = int.Parse((string)xmlElement.Attributes["rank"]);
            string elementType = this.GetElementType(xmlElement);
            int index = elementType.IndexOf("[]");
            int length = index;
            while (index != -1)
            {
                rank++;
                index = elementType.IndexOf("[]", (int)(index + 1));
            }
            if (length != -1)
            {
                elementType = elementType.Substring(0, length);
            }
            return new CodeTypeOfExpression(new CodeTypeReference(elementType, rank));
        }

        private object CreateAssignStatement(XmlElementData xmlElement)
        {
            string str = (string)xmlElement.Attributes["binaryoperator"];
            XmlElementData[] dataArray = xmlElement.Children["Expression"];
            if (str == null)
            {
                str = "equals";
            }
            string eventName = null;
            CodeExpression right = (CodeExpression)this.CreateExpressionElement(dataArray[1]);
            CodeStatement statement = null;
            switch (str)
            {
                case "equals":
                    statement = new CodeAssignStatement((CodeExpression)this.CreateExpressionElement(dataArray[0]), right);
                    goto Label_00CD;

                case "adddelegate":
                    statement = new CodeAttachEventStatement(this.GetMemberTargetObject(dataArray[0], ref eventName), eventName, right);
                    break;

                case "removedelegate":
                    statement = new CodeRemoveEventStatement(this.GetMemberTargetObject(dataArray[0], ref eventName), eventName, right);
                    break;
            }
        Label_00CD:
            if (statement != null)
            {
                XmlElementData elementExpressionStatementParent = this.GetElementExpressionStatementParent(xmlElement, false);
                if (elementExpressionStatementParent != null)
                {
                    statement.LinePragma = this.GetLinePragma(elementExpressionStatementParent);
                }
            }
            return statement;
        }

        private object CreateBaseReferenceExpression(XmlElementData xmlElement)
        {
            return new CodeBaseReferenceExpression();
        }

        private object CreateBinaryOperatorExpression(XmlElementData xmlElement)
        {
            bool flag;
            string binaryOperator = (string)xmlElement.Attributes["binaryoperator"];
            XmlElementData[] dataArray = xmlElement.Children["Expression"];
            if (binaryOperator == null)
            {
                binaryOperator = "equals";
            }
            CodeExpression left = (CodeExpression)this.CreateExpressionElement(dataArray[0]);
            CodeExpression right = (CodeExpression)this.CreateExpressionElement(dataArray[1]);
            CodeBinaryOperatorType add = CodeBinaryOperatorType.Add;
            add = this.GetBinopType(binaryOperator, out flag);
            if (!flag)
            {
                return null;
            }
            return new CodeBinaryOperatorExpression(left, add, right);
        }

        private object CreateCastExpression(XmlElementData xmlElement)
        {
            string elementType = this.GetElementType(xmlElement);
            xmlElement = xmlElement.Children.FirstChild("Expression");
            return new CodeCastExpression(elementType, (CodeExpression)this.CreateExpressionElement(xmlElement));
        }

        private object CreateCommentStatement(XmlElementData xmlElement)
        {
            return new CodeCommentStatement(xmlElement.ElementText);
        }

        private object CreateDelegateCreateExpression(XmlElementData xmlElement)
        {
            string elementText;
            CodeExpression elementExpression = this.GetElementExpression(xmlElement);
            XmlElementData[] dataArray = xmlElement.Children["Type"];
            if ((dataArray != null) && (dataArray.Length > 1))
            {
                elementText = dataArray[dataArray.Length - 1].ElementText;
            }
            else
            {
                elementText = this.GetElementType(xmlElement);
            }
            return new CodeDelegateCreateExpression(new CodeTypeReference(elementText), elementExpression, this.GetElementName(xmlElement));
        }

        private object CreateExpressionElement(XmlElementData xmlElementData)
        {
            xmlElementData = (XmlElementData)xmlElementData.Children[0];
            if (xmlElementData.ElementName == "Expression")
            {
                return this.CreateExpressionElement(xmlElementData);
            }
            return xmlElementData.CodeDomElement;
        }

        private object CreateMethodInvokeExpression(XmlElementData xmlElement)
        {
            string methodName = null;
            return new CodeMethodInvokeExpression(this.GetMemberTargetObject(xmlElement, ref methodName), methodName, this.GetElementArguments(xmlElement));
        }

        private object CreateNameReferenceExpression(XmlElementData xmlElement)
        {
            string str = (string)xmlElement.Attributes["variablekind"];
            string elementName = this.GetElementName(xmlElement);
            CodeExpression elementExpression = this.GetElementExpression(xmlElement);
            switch (str)
            {
                case "local":
                    return new CodeVariableReferenceExpression(elementName);

                case "field":
                    return new CodeFieldReferenceExpression(elementExpression, elementName);

                case "property":
                    return new CodePropertyReferenceExpression(elementExpression, elementName);

                case "method":
                    return new CodeMethodReferenceExpression(elementExpression, elementName);
            }
            return new CodeFieldReferenceExpression(elementExpression, elementName);
        }

        private object CreateObjectCreateExpression(XmlElementData xmlElement)
        {
            return new CodeObjectCreateExpression(this.GetElementType(xmlElement), this.GetElementArguments(xmlElement));
        }

        private object CreateParenthesesExpression(XmlElementData xmlElement)
        {
            xmlElement = xmlElement.Children.FirstChild("Expression");
            if (xmlElement != null)
            {
                return this.CreateExpressionElement(xmlElement);
            }
            return null;
        }

        private object CreatePrimitiveExpression(XmlElementData xmlElement)
        {
            string str2;
            xmlElement = (XmlElementData)xmlElement.Children[0];
            string elementText = xmlElement.ElementText;
            object obj2 = null;
            string elementName = xmlElement.ElementName;
            if (elementName == null)
            {
                goto Label_02B1;
            }
            elementName = string.IsInterned(elementName);
            if (elementName == "Null")
            {
                goto Label_02B3;
            }
            if (elementName != "Number")
            {
                if (elementName == "Boolean")
                {
                    goto Label_01A6;
                }
                if (elementName == "Char")
                {
                    try
                    {
                        if ((elementText == null) || (elementText.Length == 0))
                        {
                            obj2 = '\0';
                        }
                        else
                        {
                            char ch = elementText[0];
                            if ((ch & 0xff00) == 0xe000)
                            {
                                ch = (char)(ch & '\x00ff');
                            }
                            obj2 = ch;
                        }
                    }
                    catch
                    {
                        obj2 = '\0';
                    }
                    goto Label_02B3;
                }
                if (elementName == "String")
                {
                    if (elementText == null)
                    {
                        elementText = "";
                    }
                    else if ((elementText.Length == 1) && ((elementText[0] & 0xff00) == 0xe000))
                    {
                        elementText = ((char)(elementText[0] & '\x00ff')).ToString();
                    }
                    obj2 = elementText;
                    goto Label_02B3;
                }
                if (elementName == "Array")
                {
                    return xmlElement.CodeDomElement;
                }
                if (elementName == "Type")
                {
                    return new CodeTypeOfExpression(elementText);
                }
                if (elementName == "ArrayType")
                {
                    return new CodeTypeReferenceExpression(new CodeTypeReference(this.GetElementType(xmlElement), int.Parse((string)xmlElement.Attributes["rank"], CultureInfo.InvariantCulture)));
                }
                goto Label_02B1;
            }
            if (elementText.IndexOf('.') == -1)
            {
                if (elementText.EndsWith("d"))
                {
                    elementText = elementText.Substring(0, elementText.Length - 1);
                }
                try
                {
                    obj2 = int.Parse(elementText, CultureInfo.InvariantCulture);
                }
                catch (OverflowException)
                {
                    try
                    {
                        obj2 = uint.Parse(elementText, CultureInfo.InvariantCulture);
                    }
                    catch (OverflowException)
                    {
                        try
                        {
                            obj2 = long.Parse(elementText, CultureInfo.InvariantCulture);
                        }
                        catch (OverflowException)
                        {
                            try
                            {
                                obj2 = ulong.Parse(elementText, CultureInfo.InvariantCulture);
                            }
                            catch (OverflowException)
                            {
                                throw new Exception("Can't parse numeric value: '" + elementText + "'");
                            }
                        }
                    }
                }
                goto Label_02B3;
            }
            if (elementText.EndsWith("d"))
            {
                elementText = elementText.Substring(0, elementText.Length - 1);
            }
            try
            {
                obj2 = double.Parse(elementText, CultureInfo.InvariantCulture);
                goto Label_02B3;
            }
            catch (OverflowException)
            {
                throw new Exception("Can't parse numeric value: '" + elementText + "'");
            }
        Label_01A6:
            str2 = (string)xmlElement.Attributes["value"];
            obj2 = (str2 == "true") || (elementText == "true");
            goto Label_02B3;
        Label_02B1:
            return null;
        Label_02B3:
            return new CodePrimitiveExpression(obj2);
        }

        private object CreatePropertyReferenceExpression(XmlElementData xmlElement)
        {
            CodeExpression[] elementArguments = this.GetElementArguments(xmlElement);
            string member = null;
            return new CodeIndexerExpression(this.GetMemberTargetObject(xmlElement, ref member), elementArguments);
        }

        private object CreateQuoteExpression(XmlElementData xmlElement)
        {
            string str2;
            string str = xmlElement.ElementText.Replace("\t", "");
            CodeLinePragma linePragma = null;
            while ((linePragma == null) && (xmlElement != null))
            {
                linePragma = this.GetLinePragma(xmlElement);
                xmlElement = xmlElement.ParentElement;
            }
            if (linePragma == null)
            {
                linePragma = this.lastLinePragma;
            }
            if (linePragma != null)
            {
                str2 = "XmlUnknownCodeWithLine";
            }
            else
            {
                str2 = "XmlUnknownCode";
            }
            throw new CodeDomSerializerException(str2, linePragma);
        }

        private object CreateThisReferenceExpression(XmlElementData xmlElement)
        {
            return new CodeThisReferenceExpression();
        }

        private object CreateTypeOfExpression(XmlElementData xmlElement)
        {
            return new CodeTypeOfExpression(xmlElement.ElementText);
        }

        private object CreateVariableDeclarationStatement(XmlElementData xmlElement)
        {
            CodeVariableDeclarationStatement statement;
            string elementType = this.GetElementType(xmlElement);
            int count = xmlElement.Children.Count;
            CodeExpression initExpression = null;
            string elementName = this.GetElementName(xmlElement);
            if (elementName == null)
            {
                for (int i = 0; i < count; i++)
                {
                    if ((((XmlElementData)xmlElement.Children[i]).ElementName == "LocalName") && (initExpression == null))
                    {
                        elementName = ((XmlElementData)xmlElement.Children[i]).ElementText;
                        if ((i < (count - 1)) && (((XmlElementData)xmlElement.Children[i + 1]).ElementName == "Expression"))
                        {
                            initExpression = (CodeExpression)this.CreateExpressionElement((XmlElementData)xmlElement.Children[++i]);
                        }
                        else
                        {
                            initExpression = null;
                        }
                    }
                }
            }
            else
            {
                initExpression = this.GetElementExpression(xmlElement);
            }
            if (initExpression != null)
            {
                statement = new CodeVariableDeclarationStatement(elementType, elementName, initExpression);
            }
            else
            {
                statement = new CodeVariableDeclarationStatement(elementType, elementName);
            }
            statement.LinePragma = this.GetLinePragma(xmlElement);
            return statement;
        }

        public void EndAttribute(string prefix, string name, string urn)
        {
            if (this.curAttrName != null)
            {
                this.currentElement.Attributes[this.curAttrName] = "";
                this.curAttrName = null;
            }
        }

        public void EndElement(string prefix, string name, string urn)
        {
            if (name != "Block")
            {
                for (XmlElementData data = (XmlElementData)this.itemStack.Peek(); name != data.ElementName; data = (XmlElementData)this.itemStack.Peek())
                {
                    this.EndElement(prefix, data.ElementName, urn);
                    if (this.itemStack.Count <= 0)
                    {
                        return;
                    }
                }
                this.itemStack.Pop();
                object codeDomElement = this.currentElement.CodeDomElement;
                int count = this.itemStack.Count;
                if ((codeDomElement != null) && ((count == 0) || (this.currentElement.FirstParentWithHandler == null)))
                {
                    if (codeDomElement is CodeExpression)
                    {
                        codeDomElement = new CodeExpressionStatement((CodeExpression)codeDomElement);
                        XmlElementData elementExpressionStatementParent = this.GetElementExpressionStatementParent(this.currentElement, false);
                        if (elementExpressionStatementParent != null)
                        {
                            ((CodeStatement)codeDomElement).LinePragma = this.GetLinePragma(elementExpressionStatementParent);
                        }
                    }
                    ((CodeObject)codeDomElement).UserData["_XmlCodeDomParseStmt"] = "_XmlCodeDomParseStmt";
                    this.topLevelItems.Add(codeDomElement);
                    this.ReleaseDataItem(this.currentElement);
                }
                if (count > 0)
                {
                    this.currentElement = (XmlElementData)this.itemStack.Peek();
                }
                else
                {
                    this.currentElement = null;
                }
            }
        }

        public void Entity(string name)
        {
        }

        public void FinishChildren(string prefix, string name, string urn)
        {
        }

        private CodeBinaryOperatorType GetBinopType(string binaryOperator, out bool success)
        {
            if (binopTable == null)
            {
                binopTable = new Hashtable(0x12);
                binopTable["plus"] = CodeBinaryOperatorType.Add;
                binopTable["concatenate"] = CodeBinaryOperatorType.Add;
                binopTable["minus"] = CodeBinaryOperatorType.Subtract;
                binopTable["times"] = CodeBinaryOperatorType.Multiply;
                binopTable["divide"] = CodeBinaryOperatorType.Divide;
                binopTable["remainder"] = CodeBinaryOperatorType.Modulus;
                binopTable["bitand"] = CodeBinaryOperatorType.BitwiseAnd;
                binopTable["bitor"] = CodeBinaryOperatorType.BitwiseOr;
                binopTable["logicaland"] = CodeBinaryOperatorType.BooleanAnd;
                binopTable["logicalor"] = CodeBinaryOperatorType.BooleanOr;
                binopTable["equals"] = CodeBinaryOperatorType.ValueEquality;
                binopTable["notequals"] = CodeBinaryOperatorType.IdentityInequality;
                binopTable["refnotequals"] = CodeBinaryOperatorType.IdentityInequality;
                binopTable["refequals"] = CodeBinaryOperatorType.IdentityEquality;
                binopTable["greaterthan"] = CodeBinaryOperatorType.GreaterThan;
                binopTable["lessthan"] = CodeBinaryOperatorType.LessThan;
                binopTable["greaterthanorequals"] = CodeBinaryOperatorType.GreaterThanOrEqual;
                binopTable["lessthanorequals"] = CodeBinaryOperatorType.LessThanOrEqual;
            }
            object obj2 = binopTable[binaryOperator];
            if (obj2 == null)
            {
                success = false;
                return CodeBinaryOperatorType.Add;
            }
            success = true;
            return (CodeBinaryOperatorType)obj2;
        }

        private XmlElementData GetDataItem(string elementName)
        {
            XmlElementData data = null;
            if (this.garbagePile.Count == 0)
            {
                data = new XmlElementData(elementName);
            }
            else
            {
                data = (XmlElementData)this.garbagePile.Pop();
                data.Reset();
                data.ElementName = elementName;
            }
            data.HandlerHash = this.createHandlers;
            return data;
        }

        private CodeExpression[] GetElementArguments(XmlElementData xmlElement)
        {
            XmlElementData[] dataArray = xmlElement.Children["Argument"];
            if (dataArray == null)
            {
                return new CodeExpression[0];
            }
            CodeExpression[] expressionArray = new CodeExpression[dataArray.Length];
            for (int i = 0; i < expressionArray.Length; i++)
            {
                expressionArray[i] = this.GetElementExpression(dataArray[i]);
            }
            return expressionArray;
        }

        private CodeExpression GetElementExpression(XmlElementData xmlElement)
        {
            XmlElementData xmlElementData = xmlElement.Children.FirstChild("Expression");
            if (xmlElementData != null)
            {
                return (CodeExpression)this.CreateExpressionElement(xmlElementData);
            }
            return null;
        }

        private XmlElementData GetElementExpressionStatementParent(XmlElementData xmlElementData, bool immediate)
        {
            int num = 1;
            for (XmlElementData data = xmlElementData.ParentElement; (data != null) && (num >= 0); data = data.ParentElement)
            {
                if (immediate)
                {
                    num--;
                }
                if (data.ElementName == "ExpressionStatement")
                {
                    return data;
                }
            }
            return null;
        }

        private MemberAttributes GetElementModifiers(XmlElementData xmlElement)
        {
            IEnumerator enumerator = xmlElement.Attributes.Keys.GetEnumerator();
            MemberAttributes attributes = (MemberAttributes)0;
            while (enumerator.MoveNext())
            {
                string current = (string)enumerator.Current;
                if (current == "virtual")
                {
                    attributes &= ~MemberAttributes.Final;
                }
                else
                {
                    if (current == "static")
                    {
                        attributes |= MemberAttributes.Static;
                        continue;
                    }
                    if (current == "abstract")
                    {
                        attributes |= MemberAttributes.Abstract;
                        continue;
                    }
                    if (current == "shadows")
                    {
                        attributes |= MemberAttributes.New;
                        continue;
                    }
                    if (current == "overrides")
                    {
                        attributes |= MemberAttributes.Override;
                        continue;
                    }
                    if (current == "sealed")
                    {
                        attributes |= MemberAttributes.Final;
                        continue;
                    }
                    if (current == "const")
                    {
                        attributes |= MemberAttributes.Const;
                    }
                }
            }
            return attributes;
        }

        private string GetElementName(XmlElementData xmlElementData)
        {
            string elementText = (string)xmlElementData.Attributes["name"];
            if (elementText == null)
            {
                XmlElementData data = xmlElementData.Children.FirstChild("Name");
                if (data != null)
                {
                    elementText = data.ElementText;
                }
            }
            return elementText;
        }

        private string GetElementType(XmlElementData xmlData)
        {
            XmlElementData data = xmlData.Children.FirstChild("Type");
            if (data == null)
            {
                data = xmlData.Children.FirstChild("ArrayType");
                if (data != null)
                {
                    return (this.GetElementType(data) + "[]");
                }
            }
            if (data == null)
            {
                return null;
            }
            return data.ElementText;
        }

        private CodeLinePragma GetLinePragma(XmlElementData xmlElementData)
        {
            string s = (string)xmlElementData.Attributes["line"];
            CodeLinePragma pragma = null;
            if (((this.fileName != null) && (s != null)) && (s.Length > 0))
            {
                try
                {
                    pragma = new CodeLinePragma(this.fileName, int.Parse(s, CultureInfo.InvariantCulture) + 1);
                }
                catch
                {
                }
                this.lastLinePragma = pragma;
            }
            return pragma;
        }

        private CodeExpression GetMemberTargetObject(XmlElementData xmlElementData, ref string member)
        {
            XmlElementData data = xmlElementData;
            xmlElementData = xmlElementData.Children.FirstChild("NameRef");
            if (xmlElementData == null)
            {
                xmlElementData = data.Children.FirstChild("Expression");
                xmlElementData = xmlElementData.Children.FirstChild("NameRef");
                if (xmlElementData == null)
                {
                    return null;
                }
            }
            member = this.GetElementName(xmlElementData);
            xmlElementData = xmlElementData.Children.FirstChild("Expression");
            return (CodeExpression)this.CreateExpressionElement(xmlElementData);
        }

        private void InitHandlers()
        {
            if (!this.handlersInitialized)
            {
                this.createHandlers["NewArray"] = new CreateCodeExpressionHandler(this.CreateArrayCreateExpression);
                this.createHandlers["Assignment"] = new CreateCodeExpressionHandler(this.CreateAssignStatement);
                this.createHandlers["BaseReference"] = new CreateCodeExpressionHandler(this.CreateBaseReferenceExpression);
                this.createHandlers["BinaryOperation"] = new CreateCodeExpressionHandler(this.CreateBinaryOperatorExpression);
                this.createHandlers["Cast"] = new CreateCodeExpressionHandler(this.CreateCastExpression);
                this.createHandlers["NewDelegate"] = new CreateCodeExpressionHandler(this.CreateDelegateCreateExpression);
                this.createHandlers["NameRef"] = new CreateCodeExpressionHandler(this.CreateNameReferenceExpression);
                this.createHandlers["MethodCall"] = new CreateCodeExpressionHandler(this.CreateMethodInvokeExpression);
                this.createHandlers["NewClass"] = new CreateCodeExpressionHandler(this.CreateObjectCreateExpression);
                this.createHandlers["Literal"] = new CreateCodeExpressionHandler(this.CreatePrimitiveExpression);
                this.createHandlers["PropertyAccess"] = new CreateCodeExpressionHandler(this.CreatePropertyReferenceExpression);
                this.createHandlers["ThisReference"] = new CreateCodeExpressionHandler(this.CreateThisReferenceExpression);
                this.createHandlers["Local"] = new CreateCodeExpressionHandler(this.CreateVariableDeclarationStatement);
                this.createHandlers["Array"] = new CreateCodeExpressionHandler(this.CreateArrayExpression);
                this.createHandlers["Quote"] = new CreateCodeExpressionHandler(this.CreateQuoteExpression);
                this.createHandlers["Parentheses"] = new CreateCodeExpressionHandler(this.CreateParenthesesExpression);
                this.createHandlers["Type"] = new CreateCodeExpressionHandler(this.CreateTypeOfExpression);
                this.createHandlers["ArrayElementAccess"] = new CreateCodeExpressionHandler(this.CreateArrayIndexerExpression);
                this.createHandlers["Comment"] = new CreateCodeExpressionHandler(this.CreateCommentStatement);
                this.createHandlers["ArrayType"] = new CreateCodeExpressionHandler(this.CreateArrayTypeReferenceExpression);
                this.handlersInitialized = true;
            }
        }

        public void NumericEntity(char value, bool hex)
        {
        }

        private void Parse(XmlReader reader)
        {
            while (reader.Read())
            {
                switch (reader.NodeType)
                {
                    case XmlNodeType.Element:
                        this.StartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                        goto Label_00A4;

                    case XmlNodeType.Attribute:
                    case XmlNodeType.EntityReference:
                    case XmlNodeType.Entity:
                    case XmlNodeType.SignificantWhitespace:
                        {
                            continue;
                        }
                    case XmlNodeType.Text:
                        {
                            this.Text(reader.Value);
                            continue;
                        }
                    case XmlNodeType.CDATA:
                        {
                            this.CData(reader.Value);
                            continue;
                        }
                    case XmlNodeType.ProcessingInstruction:
                        {
                            this.PI(reader.Name, reader.Value);
                            continue;
                        }
                    case XmlNodeType.Comment:
                        {
                            this.Comment(reader.Value);
                            continue;
                        }
                    case XmlNodeType.Whitespace:
                        {
                            this.Whitespace(reader.Value);
                            continue;
                        }
                    case XmlNodeType.EndElement:
                        {
                            this.EndElement(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                            continue;
                        }
                    default:
                        {
                            continue;
                        }
                }
            Label_0068:
                this.StartAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI);
                this.Text(reader.Value);
                this.EndAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI);
            Label_00A4:
                if (reader.MoveToNextAttribute())
                {
                    goto Label_0068;
                }
            }
        }

        public int ParseXml(string xmlStream, CodeStatementCollection statementCollection, string fileName, string methodName)
        {
            this.InitHandlers();
            XmlTextReader reader = new XmlTextReader(new StringReader(xmlStream));
            for (int i = 0; i < NameTableStrings.Length; i++)
            {
                reader.NameTable.Add(NameTableStrings[i]);
            }
            this.topLevelItems.Clear();
            try
            {
                this.fileName = fileName;
                this.methodName = methodName;
                try
                {
                    this.Parse(reader);
                }
                catch (CodeDomSerializerException)
                {
                    throw;
                }
                catch (Exception)
                {
                    if (this.lastLinePragma != null)
                    {
                        throw new CodeDomSerializerException("XmlParseException", this.lastLinePragma);
                    }
                    throw;
                }
            }
            finally
            {
                this.fileName = null;
                this.methodName = null;
            }
            foreach (CodeStatement statement in this.topLevelItems)
            {
                statementCollection.Add(statement);
            }
            return this.topLevelItems.Count;
        }

        public void PI(string target, string body)
        {
        }

        private void ReleaseDataItem(XmlElementData dataItem)
        {
            ArrayList children = dataItem.Children;
            int num = (children == null) ? 0 : children.Count;
            for (int i = 0; i < num; i++)
            {
                this.ReleaseDataItem((XmlElementData)children[i]);
                this.garbagePile.Push(children[i]);
            }
            if (dataItem.ParentElement == null)
            {
                this.garbagePile.Push(dataItem);
            }
        }

        public void StartAttribute(string prefix, string name, string urn)
        {
            this.curAttrName = name;
        }

        public void StartChildren()
        {
        }

        public void StartElement(string prefix, string name, string urn)
        {
            XmlElementData dataItem = this.GetDataItem(name);
            if (this.currentElement != null)
            {
                this.currentElement.Children.Add(dataItem);
                dataItem.ParentElement = this.currentElement;
            }
            else
            {
                this.currentElement = null;
            }
            this.currentElement = dataItem;
            if (name != "Block")
            {
                this.itemStack.Push(this.currentElement);
            }
        }

        public void Text(string text)
        {
            if (this.curAttrName == null)
            {
                this.currentElement.ElementText = text;
            }
            else
            {
                this.currentElement.Attributes[this.curAttrName] = text;
                this.curAttrName = null;
            }
        }

        public void Whitespace(string text)
        {
        }

        // Nested Types
        internal class CodeArrayExpression : CodeExpression
        {
            // Fields
            private CodeExpressionCollection exprValues;

            // Methods
            public CodeArrayExpression()
            {
            }

            public CodeArrayExpression(CodeExpression[] values)
            {
                if ((values != null) && (values.Length > 0))
                {
                    foreach (CodeExpression expression in values)
                    {
                        this.Values.Add(expression);
                    }
                }
            }

            public CodeExpression[] CreateValueArray()
            {
                CodeExpression[] array = new CodeExpression[this.Length];
                if (this.Length > 0)
                {
                    this.exprValues.CopyTo(array, 0);
                }
                return array;
            }

            // Properties
            public int Length
            {
                get
                {
                    if (this.exprValues == null)
                    {
                        return 0;
                    }
                    return this.exprValues.Count;
                }
            }

            public CodeExpressionCollection Values
            {
                get
                {
                    if (this.exprValues == null)
                    {
                        this.exprValues = new CodeExpressionCollection();
                    }
                    return this.exprValues;
                }
            }
        }

        protected delegate object CreateCodeExpressionHandler(CodeDomXmlProcessor.XmlElementData itemData);

        protected class XmlElementData
        {
            // Fields
            private IDictionary attributes;
            private XmlChildren children;
            private object codeExpression;
            private bool createFailed;
            private CodeDomXmlProcessor.CreateCodeExpressionHandler createHandler;
            public string ElementName;
            public string ElementText;
            public Hashtable HandlerHash;
            public CodeDomXmlProcessor.XmlElementData ParentElement;
            private object parentWithHandler = "checkit";

            // Methods
            public XmlElementData(string elementName)
            {
                this.ElementName = elementName;
            }

            public void Reset()
            {
                this.ElementName = null;
                this.ElementText = null;
                this.codeExpression = null;
                this.createHandler = null;
                this.ParentElement = null;
                this.HandlerHash = null;
                this.createFailed = false;
                this.parentWithHandler = "checkit";
                if (this.attributes != null)
                {
                    this.attributes.Clear();
                }
                if (this.children != null)
                {
                    this.children.Clear();
                }
            }

            public override string ToString()
            {
                string elementName = this.ElementName;
                if (this.ElementText != null)
                {
                    elementName = elementName + ", text='" + this.ElementText + "'";
                }
                if (this.children != null)
                {
                    object obj2 = elementName;
                    elementName = string.Concat(new object[] { obj2, ", ", this.children.Count, " children" });
                }
                if (this.codeExpression != null)
                {
                    elementName = elementName + "expr=" + this.codeExpression.GetType().Name;
                }
                return elementName;
            }

            // Properties
            public IDictionary Attributes
            {
                get
                {
                    if (this.attributes == null)
                    {
                        this.attributes = new Hashtable();
                    }
                    return this.attributes;
                }
            }

            public XmlChildren Children
            {
                get
                {
                    if (this.children == null)
                    {
                        this.children = new XmlChildren();
                    }
                    return this.children;
                }
            }

            public object CodeDomElement
            {
                get
                {
                    if ((this.codeExpression == null) && (this.CreateHandler != null))
                    {
                        this.codeExpression = this.CreateHandler(this);
                        this.createFailed = this.codeExpression == null;
                    }
                    return this.codeExpression;
                }
            }

            private CodeDomXmlProcessor.CreateCodeExpressionHandler CreateHandler
            {
                get
                {
                    if ((!this.createFailed && (this.HandlerHash != null)) && (this.createHandler == null))
                    {
                        this.createHandler = (CodeDomXmlProcessor.CreateCodeExpressionHandler)this.HandlerHash[this.ElementName];
                        if (this.createHandler == null)
                        {
                            this.createFailed = true;
                            return null;
                        }
                    }
                    return this.createHandler;
                }
            }

            public CodeDomXmlProcessor.XmlElementData FirstParentWithHandler
            {
                get
                {
                    if (this.parentWithHandler is string)
                    {
                        CodeDomXmlProcessor.XmlElementData parentElement = this.ParentElement;
                        while ((parentElement != null) && !parentElement.HasHandler)
                        {
                            parentElement = parentElement.ParentElement;
                        }
                        this.parentWithHandler = parentElement;
                    }
                    return (CodeDomXmlProcessor.XmlElementData)this.parentWithHandler;
                }
            }

            public bool HasHandler
            {
                get
                {
                    return (this.CreateHandler != null);
                }
            }

            // Nested Types
            public class XmlChildren : ArrayList
            {
                // Methods
                public CodeDomXmlProcessor.XmlElementData FirstChild(string name)
                {
                    int count = base.Count;
                    for (int i = 0; i < count; i++)
                    {
                        CodeDomXmlProcessor.XmlElementData data = (CodeDomXmlProcessor.XmlElementData)this[i];
                        if (data.ElementName == name)
                        {
                            return data;
                        }
                    }
                    return null;
                }

                // Properties
                public CodeDomXmlProcessor.XmlElementData[] this[string name]
                {
                    get
                    {
                        ArrayList list = null;
                        int count = base.Count;
                        for (int i = 0; i < count; i++)
                        {
                            CodeDomXmlProcessor.XmlElementData data = (CodeDomXmlProcessor.XmlElementData)this[i];
                            if (data.ElementName == name)
                            {
                                if (list == null)
                                {
                                    list = new ArrayList();
                                }
                                list.Add(this[i]);
                            }
                        }
                        if (list == null)
                        {
                            return new CodeDomXmlProcessor.XmlElementData[0];
                        }
                        CodeDomXmlProcessor.XmlElementData[] array = new CodeDomXmlProcessor.XmlElementData[list.Count];
                        list.CopyTo(array, 0);
                        return array;
                    }
                }
            }
        }
    }
}
